home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / mklev.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  33.8 KB  |  1,415 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)mklev.c    3.1    93/02/21    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. /* #define DEBUG     /* uncomment to enable code debugging */
  7.  
  8. #ifdef DEBUG
  9. # ifdef WIZARD
  10. #define debugpline    if (wizard) pline
  11. # else
  12. #define debugpline    pline
  13. # endif
  14. #endif
  15.  
  16. /* for UNIX, Rand #def'd to (long)lrand48() or (long)random() */
  17. /* croom->lx etc are schar (width <= int), so % arith ensures that */
  18. /* conversion of result to int is reasonable */
  19.  
  20.  
  21. static void FDECL(mkfount,(int,struct mkroom *));
  22. #ifdef SINKS
  23. static void FDECL(mksink,(struct mkroom *));
  24. #endif
  25. static void FDECL(mkaltar,(struct mkroom *));
  26. static void NDECL(makevtele);
  27. static void NDECL(clear_level_structures);
  28. static void NDECL(makelevel);
  29. static boolean FDECL(bydoor,(XCHAR_P,XCHAR_P));
  30. static struct mkroom *FDECL(find_branch_room, (coord *));
  31. static struct mkroom *FDECL(pos_to_room, (XCHAR_P, XCHAR_P));
  32. static boolean FDECL(place_niche,(struct mkroom *,int*,int*,int*));
  33. static void FDECL(makeniche,(int));
  34. static void NDECL(make_niches);
  35. STATIC_PTR int FDECL(do_comp,(const genericptr,const genericptr));
  36. static void FDECL(dosdoor,(XCHAR_P,XCHAR_P,struct mkroom *,int));
  37. static void FDECL(join,(int,int,BOOLEAN_P));
  38. static void FDECL(do_room_or_subroom, (struct mkroom *,int,int,int,int,
  39.                        BOOLEAN_P,SCHAR_P,BOOLEAN_P,BOOLEAN_P));
  40. static void NDECL(makerooms);
  41. static void FDECL(finddpos,(coord *,XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P));
  42. static void FDECL(mkinvpos, (XCHAR_P,XCHAR_P,int));
  43. #ifdef MULDGN
  44. static void FDECL(mk_knox_portal, (XCHAR_P,XCHAR_P));
  45. #endif
  46.  
  47. #define create_vault()    create_room(-1, -1, 2, 2, -1, -1, VAULT, TRUE)
  48. #define init_vault()    vault_x = -1
  49. #define do_vault()    (vault_x != -1)
  50. static xchar        vault_x, vault_y;
  51. boolean goldseen;
  52. static boolean made_branch;    /* used only during level creation */
  53.  
  54. /* Args must be (const genericptr) so that qsort will always be happy. */
  55.  
  56. STATIC_PTR int
  57. do_comp(vx,vy)
  58. const genericptr vx;
  59. const genericptr vy;
  60. {
  61. #ifdef LINT
  62. /* lint complains about possible pointer alignment problems, but we know
  63.    that vx and vy are always properly aligned. Hence, the following
  64.    bogus definition:
  65. */
  66.     return (vx == vy) ? 0 : -1;
  67. #else
  68.     register const struct mkroom *x, *y;
  69.  
  70.     x = (const struct mkroom *)vx;
  71.     y = (const struct mkroom *)vy;
  72.     if(x->lx < y->lx) return(-1);
  73.     return(x->lx > y->lx);
  74. #endif /* LINT */
  75. }
  76.  
  77. static void
  78. finddpos(cc, xl,yl,xh,yh)
  79. coord    *cc;
  80. xchar    xl,yl,xh,yh;
  81. {
  82.     register xchar x, y;
  83.  
  84.     x = (xl == xh) ? xl : (xl + rn2(xh-xl+1));
  85.     y = (yl == yh) ? yl : (yl + rn2(yh-yl+1));
  86.     if(okdoor(x, y))
  87.         goto gotit;
  88.  
  89.     for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
  90.         if(okdoor(x, y))
  91.             goto gotit;
  92.  
  93.     for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
  94.         if(IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR)
  95.             goto gotit;
  96.     /* cannot find something reasonable -- strange */
  97.     x = xl;
  98.     y = yh;
  99. gotit:
  100.     cc->x = x;
  101.     cc->y = y;
  102.     return;
  103. }
  104.  
  105. void
  106. sort_rooms()
  107. {
  108. #if defined(SYSV) || defined(DGUX)
  109.     qsort((genericptr_t) rooms, (unsigned)nroom, sizeof(struct mkroom), do_comp);
  110. #else
  111.     qsort((genericptr_t) rooms, nroom, sizeof(struct mkroom), do_comp);
  112. #endif
  113. }
  114.  
  115. static void
  116. do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special, is_room)
  117.     register struct mkroom *croom;
  118.     int lowx, lowy;
  119.     register int hix, hiy;
  120.     boolean lit;
  121.     schar rtype;
  122.     boolean special;
  123.     boolean is_room;
  124. {
  125.     register int x, y;
  126.     struct rm *lev;
  127.  
  128.     /* locations might bump level edges in wall-less rooms */
  129.     /* add/subtract 1 to allow for edge locations */
  130.     if(!lowx) lowx++;
  131.     if(!lowy) lowy++;
  132.     if(hix >= COLNO-1) hix = COLNO-2;
  133.     if(hiy >= ROWNO-1) hiy = ROWNO-2;
  134.  
  135.     if(lit) {
  136.         for(x = lowx-1; x <= hix+1; x++) {
  137.             lev = &levl[x][max(lowy-1,0)];
  138.             for(y = lowy-1; y <= hiy+1; y++)
  139.                 lev++->lit = 1;
  140.         }
  141.         croom->rlit = 1;
  142.     } else
  143.         croom->rlit = 0;
  144.  
  145.     croom->lx = lowx;
  146.     croom->hx = hix;
  147.     croom->ly = lowy;
  148.     croom->hy = hiy;
  149.     croom->rtype = rtype;
  150.     croom->doorct = 0;
  151.     /* if we're not making a vault, doorindex will still be 0
  152.      * if we are, we'll have problems adding niches to the previous room
  153.      * unless fdoor is at least doorindex
  154.      */
  155.     croom->fdoor = doorindex;
  156.     croom->irregular = FALSE;
  157.  
  158.     croom->nsubrooms = 0;
  159.     croom->sbrooms[0] = (struct mkroom *) 0;
  160.     if (!special) {
  161.         for(x = lowx-1; x <= hix+1; x++)
  162.         for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
  163.             levl[x][y].typ = HWALL;
  164.             levl[x][y].horizontal = 1;    /* For open/secret doors. */
  165.         }
  166.         for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
  167.         for(y = lowy; y <= hiy; y++) {
  168.             levl[x][y].typ = VWALL;
  169.             levl[x][y].horizontal = 0;    /* For open/secret doors. */
  170.         }
  171.         for(x = lowx; x <= hix; x++) {
  172.         lev = &levl[x][lowy];
  173.         for(y = lowy; y <= hiy; y++)
  174.             lev++->typ = ROOM;
  175.         }
  176.         if (is_room) {
  177.         levl[lowx-1][lowy-1].typ = TLCORNER;
  178.         levl[hix+1][lowy-1].typ = TRCORNER;
  179.         levl[lowx-1][hiy+1].typ = BLCORNER;
  180.         levl[hix+1][hiy+1].typ = BRCORNER;
  181.         } else {    /* a subroom */
  182.         wallification(lowx-1, lowy-1, hix+1, hiy+1);
  183.         }
  184.     }
  185. }
  186.  
  187.  
  188. void
  189. add_room(lowx, lowy, hix, hiy, lit, rtype, special)
  190. register int lowx, lowy, hix, hiy;
  191. boolean lit;
  192. schar rtype;
  193. boolean special;
  194. {
  195.     register struct mkroom *croom;
  196.  
  197.     croom = &rooms[nroom];
  198.     do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit,
  199.                         rtype, special, (boolean) TRUE);
  200.     croom++;
  201.     croom->hx = -1;
  202.     nroom++;
  203. }
  204.  
  205. void
  206. add_subroom(proom, lowx, lowy, hix, hiy, lit, rtype, special)
  207. struct mkroom *proom;
  208. register int lowx, lowy, hix, hiy;
  209. boolean lit;
  210. schar rtype;
  211. boolean special;
  212. {
  213.     register struct mkroom *croom;
  214.  
  215.     croom = &subrooms[nsubroom];
  216.     do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit,
  217.                         rtype, special, (boolean) FALSE);
  218.     proom->sbrooms[proom->nsubrooms++] = croom;
  219.     croom++;
  220.     croom->hx = -1;
  221.     nsubroom++;
  222. }
  223.  
  224. static void
  225. makerooms()
  226. {
  227.     boolean tried_vault = FALSE;
  228.  
  229.     /* make rooms until satisfied */
  230.     /* rnd_rect() will returns 0 if no more rects are available... */
  231.     while(nroom < MAXNROFROOMS && rnd_rect()) {
  232.         if(nroom >= (MAXNROFROOMS/6) && rn2(2) && !tried_vault) {
  233.             tried_vault = TRUE;
  234.             if (create_vault()) {
  235.                 vault_x = rooms[nroom].lx;
  236.                 vault_y = rooms[nroom].ly;
  237.                 rooms[nroom].hx = -1;
  238.             }
  239.         } else
  240.             if (!create_room(-1, -1, -1, -1, -1, -1, OROOM, -1))
  241.             return;
  242.     }
  243.     return;
  244. }
  245.  
  246. static void
  247. join(a,b,nxcor)
  248. register int a, b;
  249. boolean nxcor;
  250. {
  251.     coord cc,tt, org, dest;
  252.     register int tx, ty, xx, yy;
  253.     register struct mkroom *croom, *troom;
  254.     register int dx, dy;
  255.  
  256.     croom = &rooms[a];
  257.     troom = &rooms[b];
  258.  
  259.     /* find positions cc and tt for doors in croom and troom
  260.        and direction for a corridor between them */
  261.  
  262.     if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return;
  263.     if(troom->lx > croom->hx) {
  264.         dx = 1;
  265.         dy = 0;
  266.         xx = croom->hx+1;
  267.         tx = troom->lx-1;
  268.         finddpos(&cc, xx, croom->ly, xx, croom->hy);
  269.         finddpos(&tt, tx, troom->ly, tx, troom->hy);
  270.     } else if(troom->hy < croom->ly) {
  271.         dy = -1;
  272.         dx = 0;
  273.         yy = croom->ly-1;
  274.         finddpos(&cc, croom->lx, yy, croom->hx, yy);
  275.         ty = troom->hy+1;
  276.         finddpos(&tt, troom->lx, ty, troom->hx, ty);
  277.     } else if(troom->hx < croom->lx) {
  278.         dx = -1;
  279.         dy = 0;
  280.         xx = croom->lx-1;
  281.         tx = troom->hx+1;
  282.         finddpos(&cc, xx, croom->ly, xx, croom->hy);
  283.         finddpos(&tt, tx, troom->ly, tx, troom->hy);
  284.     } else {
  285.         dy = 1;
  286.         dx = 0;
  287.         yy = croom->hy+1;
  288.         ty = troom->ly-1;
  289.         finddpos(&cc, croom->lx, yy, croom->hx, yy);
  290.         finddpos(&tt, troom->lx, ty, troom->hx, ty);
  291.     }
  292.     xx = cc.x;
  293.     yy = cc.y;
  294.     tx = tt.x - dx;
  295.     ty = tt.y - dy;
  296.     if(nxcor && levl[xx+dx][yy+dy].typ)
  297.         return;
  298.     if (okdoor(xx,yy) || !nxcor)
  299.         dodoor(xx,yy,croom);
  300.  
  301.     org.x  = xx+dx; org.y  = yy+dy;
  302.     dest.x = tx; dest.y = ty;
  303.  
  304.     if (!dig_corridor(org, dest, nxcor, CORR, STONE))
  305.         return;
  306.  
  307.     /* we succeeded in digging the corridor */
  308.     if (okdoor(tt.x, tt.y) || !nxcor)
  309.         dodoor(tt.x, tt.y, troom);
  310.  
  311.     if(smeq[a] < smeq[b])
  312.         smeq[b] = smeq[a];
  313.     else
  314.         smeq[a] = smeq[b];
  315. }
  316.  
  317. void
  318. makecorridors()
  319. {
  320.     int a, b, i;
  321.     boolean any = TRUE;
  322.  
  323.     for(a = 0; a < nroom-1; a++) {
  324.         join(a, a+1, FALSE);
  325.         if(!rn2(50)) break; /* allow some randomness */
  326.     }
  327.     for(a = 0; a < nroom-2; a++)
  328.         if(smeq[a] != smeq[a+2])
  329.         join(a, a+2, FALSE);
  330.     for(a = 0; any && a < nroom; a++) {
  331.         any = FALSE;
  332.         for(b = 0; b < nroom; b++)
  333.         if(smeq[a] != smeq[b]) {
  334.             join(a, b, FALSE);
  335.             any = TRUE;
  336.         }
  337.     }
  338.     if(nroom > 2)
  339.         for(i = rn2(nroom) + 4; i; i--) {
  340.         a = rn2(nroom);
  341.         b = rn2(nroom-2);
  342.         if(b >= a) b += 2;
  343.         join(a, b, TRUE);
  344.         }
  345. }
  346.  
  347. void
  348. add_door(x,y,aroom)
  349. register int x, y;
  350. register struct mkroom *aroom;
  351. {
  352.     register struct mkroom *broom;
  353.     register int tmp;
  354.  
  355.     aroom->doorct++;
  356.     broom = aroom+1;
  357.     if(broom->hx < 0)
  358.         tmp = doorindex;
  359.     else
  360.         for(tmp = doorindex; tmp > broom->fdoor; tmp--)
  361.             doors[tmp] = doors[tmp-1];
  362.     doorindex++;
  363.     doors[tmp].x = x;
  364.     doors[tmp].y = y;
  365.     for( ; broom->hx >= 0; broom++) broom->fdoor++;
  366. }
  367.  
  368. static void
  369. dosdoor(x,y,aroom,type)
  370. register xchar x, y;
  371. register struct mkroom *aroom;
  372. register int type;
  373. {
  374.     boolean shdoor = ((*in_rooms(x, y, SHOPBASE))? TRUE : FALSE);
  375.  
  376.     if(!IS_WALL(levl[x][y].typ)) /* avoid SDOORs on already made doors */
  377.         type = DOOR;
  378.     levl[x][y].typ = type;
  379.     if(type == DOOR) {
  380.         if(!rn2(3)) {      /* is it a locked door, closed, or a doorway? */
  381.         if(!rn2(5))
  382.             levl[x][y].doormask = D_ISOPEN;
  383.         else if(!rn2(6))
  384.             levl[x][y].doormask = D_LOCKED;
  385.         else
  386.             levl[x][y].doormask = D_CLOSED;
  387.  
  388.         if (levl[x][y].doormask != D_ISOPEN && !shdoor &&
  389.             level_difficulty() >= 5 && !rn2(25))
  390.             levl[x][y].doormask |= D_TRAPPED;
  391.         } else
  392. #ifdef STUPID
  393.         if (shdoor)
  394.             levl[x][y].doormask = D_ISOPEN;
  395.         else
  396.             levl[x][y].doormask = D_NODOOR;
  397. #else
  398.         levl[x][y].doormask = (shdoor ? D_ISOPEN : D_NODOOR);
  399. #endif
  400.         if(levl[x][y].doormask & D_TRAPPED) {
  401.         struct monst *mtmp;
  402.  
  403.         if (level_difficulty() >= 9 && !rn2(5) &&
  404.            !((mons[PM_SMALL_MIMIC].geno & (G_GENOD | G_EXTINCT)) &&
  405.              (mons[PM_LARGE_MIMIC].geno & (G_GENOD | G_EXTINCT)) &&
  406.              (mons[PM_GIANT_MIMIC].geno & (G_GENOD | G_EXTINCT)))) {
  407.             /* make a mimic instead */
  408.             levl[x][y].doormask = D_NODOOR;
  409.             mtmp = makemon(mkclass(S_MIMIC,0), x, y);
  410.             if (mtmp)
  411.             set_mimic_sym(mtmp);
  412.         }
  413.         }
  414.         /* newsym(x,y); */
  415.     } else { /* SDOOR */
  416.         if(shdoor || !rn2(5))    levl[x][y].doormask = D_LOCKED;
  417.         else            levl[x][y].doormask = D_CLOSED;
  418.  
  419.         if(!shdoor && level_difficulty() >= 4 && !rn2(20))
  420.             levl[x][y].doormask |= D_TRAPPED;
  421.     }
  422.  
  423.     add_door(x,y,aroom);
  424. }
  425.  
  426. static boolean
  427. place_niche(aroom,dy,xx,yy)
  428. register struct mkroom *aroom;
  429. int *dy, *xx, *yy;
  430. {
  431.     coord dd;
  432.  
  433.     if(rn2(2)) {
  434.         *dy = 1;
  435.         finddpos(&dd, aroom->lx, aroom->hy+1, aroom->hx, aroom->hy+1);
  436.     } else {
  437.         *dy = -1;
  438.         finddpos(&dd, aroom->lx, aroom->ly-1, aroom->hx, aroom->ly-1);
  439.     }
  440.     *xx = dd.x;
  441.     *yy = dd.y;
  442.     return((boolean)((isok(*xx,*yy+*dy) && levl[*xx][*yy+*dy].typ == STONE)
  443.         && (isok(*xx,*yy-*dy) && !IS_POOL(levl[*xx][*yy-*dy].typ)
  444.                   && !IS_FURNITURE(levl[*xx][*yy-*dy].typ))));
  445. }
  446.  
  447. /* there should be one of these per trap, in the same order as trap.h */
  448. static NEARDATA const char *trap_engravings[TRAPNUM] = {
  449.                 NULL, NULL, NULL, NULL, NULL, NULL,
  450.                 NULL, NULL, NULL, NULL, NULL, NULL,
  451.             /* 12..14: trapdoor, teleport, level-teleport */
  452.                 "?la? ?as ?er?", "ad ae?ar um", "ad ae?ar um",
  453.                 NULL, NULL, NULL, NULL, NULL,
  454. #ifdef POLYSELF
  455.                 NULL,
  456. #endif
  457. };
  458.  
  459. static void
  460. makeniche(trap_type)
  461. int trap_type;
  462. {
  463.     register struct mkroom *aroom;
  464.     register struct rm *rm;
  465.     register int vct = 8;
  466.     int dy, xx, yy;
  467.     register struct trap *ttmp;
  468.  
  469.     if(doorindex < DOORMAX)
  470.       while(vct--) {
  471.         aroom = &rooms[rn2(nroom)];
  472.         if(aroom->rtype != OROOM) continue;    /* not an ordinary room */
  473.         if(aroom->doorct == 1 && rn2(5)) continue;
  474.         if(!place_niche(aroom,&dy,&xx,&yy)) continue;
  475.  
  476.         rm = &levl[xx][yy+dy];
  477.         if(trap_type || !rn2(4)) {
  478.  
  479.         rm->typ = SCORR;
  480.         if(trap_type) {
  481.             if(trap_type == TRAPDOOR && !Can_fall_thru(&u.uz))
  482.             trap_type = ROCKTRAP;
  483.             ttmp = maketrap(xx, yy+dy, trap_type);
  484.             if (ttmp) {
  485.             ttmp->once = 1;
  486.             if (trap_engravings[trap_type])
  487.                 make_engr_at(xx, yy-dy,
  488.                      trap_engravings[trap_type], 0L, DUST);
  489.             }
  490.         }
  491.         dosdoor(xx, yy, aroom, SDOOR);
  492.         } else {
  493.         rm->typ = CORR;
  494.         if(rn2(7))
  495.             dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR);
  496.         else {
  497.             if (!level.flags.noteleport)
  498.             (void) mksobj_at(SCR_TELEPORTATION, xx, yy+dy, TRUE);
  499.             if(!rn2(3)) (void) mkobj_at(0, xx, yy+dy, TRUE);
  500.         }
  501.         }
  502.         return;
  503.     }
  504. }
  505.  
  506. static void
  507. make_niches()
  508. {
  509.     register int ct = rnd((nroom>>1) + 1), dep = depth(&u.uz);
  510.  
  511.     boolean    ltptr = (!level.flags.noteleport && dep > 15),
  512.         vamp = (dep > 5 && dep < 25);
  513.  
  514.     while(ct--) {
  515.         if (ltptr && !rn2(6)) {
  516.             ltptr = FALSE;
  517.             makeniche(LEVEL_TELEP);
  518.         } else if (vamp && !rn2(6)) {
  519.             vamp = FALSE;
  520.             makeniche(TRAPDOOR);
  521.         } else    makeniche(NO_TRAP);
  522.     }
  523. }
  524.  
  525. static void
  526. makevtele()
  527. {
  528.     makeniche(TELEP_TRAP);
  529. }
  530.  
  531. /* clear out various globals that keep information on the current level.
  532.  * some of this is only necessary for some types of levels (maze, normal,
  533.  * special) but it's easier to put it all in one place than make sure
  534.  * each type initializes what it needs to separately.
  535.  */
  536. static void
  537. clear_level_structures()
  538. {
  539.     static struct rm zerorm = { cmap_to_glyph(S_stone),
  540.                         0, 0, 0, 0, 0, 0, 0, 0 };
  541.     register int x,y;
  542.     register struct rm *lev;
  543.  
  544.     for(x=0; x<COLNO; x++) {
  545.         lev = &levl[x][0];
  546.         for(y=0; y<ROWNO; y++) {
  547.         *lev++ = zerorm;
  548. #ifdef MICROPORT_BUG
  549.         level.objects[x][y] = (struct obj *)0;
  550.         level.monsters[x][y] = (struct monst *)0;
  551. #endif
  552.         }
  553.     }
  554. #ifndef MICROPORT_BUG
  555.     (void) memset((genericptr_t)level.objects, 0, sizeof(level.objects));
  556.     (void) memset((genericptr_t)level.monsters, 0, sizeof(level.monsters));
  557. #endif
  558.     level.objlist = (struct obj *)0;
  559.     level.buriedobjlist = (struct obj *)0;
  560.     level.monlist = (struct monst *)0;
  561.     level.damagelist = (struct damage *)0;
  562.  
  563.     level.flags.nfountains = 0;
  564.     level.flags.nsinks = 0;
  565.     level.flags.has_shop = 0;
  566.     level.flags.has_vault = 0;
  567.     level.flags.has_zoo = 0;
  568.     level.flags.has_court = 0;
  569.     level.flags.has_morgue = 0;
  570.     level.flags.has_beehive = 0;
  571. #ifdef ARMY
  572.     level.flags.has_barracks = 0;
  573. #endif
  574.     level.flags.has_temple = 0;
  575.     level.flags.has_swamp = 0;
  576.     level.flags.noteleport = 0;
  577.     level.flags.hardfloor = 0;
  578.     level.flags.nommap = 0;
  579.     level.flags.hero_memory = 1;
  580.     level.flags.shortsighted = 0;
  581.     level.flags.is_maze_lev = 0;
  582.     level.flags.is_cavernous_lev = 0;
  583.  
  584.     nroom = 0;
  585.     rooms[0].hx = -1;
  586.     nsubroom = 0;
  587.     subrooms[0].hx = -1;
  588.     doorindex = 0;
  589.     init_rect();
  590.     init_vault();
  591.     xdnstair = ydnstair = xupstair = yupstair = 0;
  592.     sstairs.sx = sstairs.sy = 0;
  593.     xdnladder = ydnladder = xupladder = yupladder = 0;
  594.     made_branch = FALSE;
  595. }
  596.  
  597. static void
  598. makelevel()
  599. {
  600.     register struct mkroom *croom, *troom;
  601.     register int tryct;
  602.     register int x, y;
  603.     struct monst *tmonst;    /* always put a web with a spider */
  604.  
  605.     if(wiz1_level.dlevel == 0) init_dungeons();
  606.     oinit();    /* assign level dependent obj probabilities */
  607.     clear_level_structures();
  608.  
  609.     {
  610.         register s_level *slev = Is_special(&u.uz);
  611.  
  612.         /* check for special levels */
  613. #ifdef REINCARNATION
  614.         if (slev && !Is_rogue_level(&u.uz))
  615. #else
  616.         if (slev)
  617. #endif
  618.         {
  619.             makemaz(slev->proto);
  620.             return;
  621.         } else if (dungeons[u.uz.dnum].proto[0]) {
  622.             makemaz("");
  623.             return;
  624. #ifdef MULDGN
  625.         } else if (In_mines(&u.uz)) {
  626.             makemaz("minefill");
  627.             return;
  628.         } else if (In_quest(&u.uz)) {
  629.             char    fillname[9];
  630.             s_level    *loc_lev;
  631.  
  632.             Sprintf(fillname, "%c-locate", pl_character[0]);
  633.             loc_lev = find_level(fillname);
  634.  
  635.             Sprintf(fillname, "%c-fill", pl_character[0]);
  636.             Strcat(fillname,
  637.                (u.uz.dlevel < loc_lev->dlevel.dlevel) ? "a" : "b");
  638.             makemaz(fillname);
  639.             return;
  640. #endif
  641.         } else if(In_hell(&u.uz) ||
  642.           (rn2(5) && u.uz.dnum == medusa_level.dnum
  643.               && depth(&u.uz) > depth(&medusa_level))) {
  644.             makemaz("");
  645.             return;
  646.         }
  647.     }
  648.  
  649.     /* otherwise, fall through - it's a "regular" level. */
  650.  
  651. #ifdef REINCARNATION
  652.     if (Is_rogue_level(&u.uz)) {
  653.         makeroguerooms();
  654.         makerogueghost();
  655.     } else
  656. #endif
  657.         makerooms();
  658.     sort_rooms();
  659.  
  660.     /* construct stairs (up and down in different rooms if possible) */
  661.     croom = &rooms[rn2(nroom)];
  662.     if (!Is_botlevel(&u.uz))
  663.          mkstairs(somex(croom), somey(croom), 0, croom);    /* down */
  664.     if (nroom > 1) {
  665.         troom = croom;
  666.         croom = &rooms[rn2(nroom-1)];
  667.         if (croom == troom) croom++;
  668.     }
  669.  
  670.     if (u.uz.dlevel != 1) {
  671.         xchar sx, sy;
  672.         do {
  673.         sx = somex(croom);
  674.         sy = somey(croom);
  675.         } while(occupied(sx, sy));
  676.         mkstairs(sx, sy, 1, croom);    /* up */
  677.     }
  678.  
  679. #ifdef REINCARNATION
  680.     if (Is_rogue_level(&u.uz)) goto skip0;
  681. #endif
  682.     makecorridors();
  683.     make_niches();
  684.  
  685.     /* make a secret treasure vault, not connected to the rest */
  686.     if(do_vault()) {
  687.         xchar w,h;
  688. #ifdef DEBUG
  689.         debugpline("trying to make a vault...");
  690. #endif
  691.         w = 1;
  692.         h = 1;
  693.         if (check_room(&vault_x, &w, &vault_y, &h, TRUE)) {
  694.             fill_vault:
  695.             add_room(vault_x, vault_y, vault_x+w,
  696.                  vault_y+h, TRUE, VAULT, FALSE);
  697.             level.flags.has_vault = 1;
  698.             fill_room(&rooms[nroom - 1], FALSE);
  699. #ifdef MULDGN
  700.             mk_knox_portal(vault_x+w, vault_y+h);
  701. #endif
  702.             if(!level.flags.noteleport && !rn2(3)) makevtele();
  703.         } else if(rnd_rect() && create_vault()) {
  704.             vault_x = rooms[nroom].lx;
  705.             vault_y = rooms[nroom].ly;
  706.             if (check_room(&vault_x, &w, &vault_y, &h, TRUE))
  707.                 goto fill_vault;
  708.             else
  709.                 rooms[nroom].hx = -1;
  710.         }
  711.     }
  712.  
  713. #ifdef WIZARD
  714.     if(wizard && getenv("SHOPTYPE")) mkroom(SHOPBASE); else
  715. #endif
  716.     if(depth(&u.uz) > 1 &&
  717.        depth(&u.uz) < depth(&medusa_level) &&
  718.        rn2(depth(&u.uz)) < 3) mkroom(SHOPBASE);
  719.     else if(depth(&u.uz) > 4 && !rn2(6)) mkroom(COURT);
  720.     else if(depth(&u.uz) > 6 && !rn2(7)) mkroom(ZOO);
  721.     else if(depth(&u.uz) > 8 && !rn2(5)) mkroom(TEMPLE);
  722.     else if(depth(&u.uz) > 9 && !rn2(5) &&
  723.        !(mons[PM_KILLER_BEE].geno & (G_GENOD | G_EXTINCT))) mkroom(BEEHIVE);
  724.     else if(depth(&u.uz) > 11 && !rn2(6)) mkroom(MORGUE);
  725.     else
  726. #ifdef ARMY
  727.     if(depth(&u.uz) > 14 && !rn2(4) &&
  728.        !(mons[PM_SOLDIER].geno & (G_GENOD | G_EXTINCT))) mkroom(BARRACKS);
  729.     else
  730. #endif
  731.     if(depth(&u.uz) > 18 && !rn2(6)) mkroom(SWAMP);
  732.  
  733. #ifdef REINCARNATION
  734. skip0:
  735. #endif
  736.     /* Place multi-dungeon branch. */
  737.     place_branch(Is_branchlev(&u.uz), 0, 0);
  738.  
  739.     /* for each room: put things inside */
  740.     for(croom = rooms; croom->hx > 0; croom++) {
  741.         if(croom->rtype != OROOM) continue;
  742.  
  743.         /* put a sleeping monster inside */
  744.         /* Note: monster may be on the stairs. This cannot be
  745.            avoided: maybe the player fell through a trap door
  746.            while a monster was on the stairs. Conclusion:
  747.            we have to check for monsters on the stairs anyway. */
  748.  
  749.         if(u.uhave.amulet || !rn2(3)) {
  750.             x = somex(croom); y = somey(croom);
  751.             tmonst = makemon((struct permonst *) 0, x,y);
  752.             if (tmonst && tmonst->data == &mons[PM_GIANT_SPIDER] &&
  753.             !is_pool(x,y))
  754.             (void) maketrap (x,y,WEB);
  755.         }
  756.         /* put traps and mimics inside */
  757.         goldseen = FALSE;
  758.         x = 8 - (level_difficulty()/6);
  759.         if (x <= 1) x = 2;
  760.         while (!rn2(x))
  761.             mktrap(0,0,croom,(coord*)0);
  762.         if(!goldseen && !rn2(3)) mkgold(0L, somex(croom), somey(croom));
  763. #ifdef REINCARNATION
  764.         if(Is_rogue_level(&u.uz)) goto skip_nonrogue;
  765. #endif
  766.         if(!rn2(10)) mkfount(0,croom);
  767. #ifdef SINKS
  768.         if(!rn2(60)) mksink(croom);
  769. #endif
  770.         if(!rn2(60)) mkaltar(croom);
  771.         /* put statues inside */
  772.         if(!rn2(20))
  773.             (void) mkcorpstat(STATUE, (struct permonst *)0,
  774.                       somex(croom), somey(croom), TRUE);
  775.  
  776.         /* put box/chest inside;
  777.          *  40% chance for at least 1 box, regardless of number
  778.          *  of rooms; about 5 - 7.5% for 2 boxes, least likely
  779.          *  when few rooms; chance for 3 or more is neglible.
  780.          */
  781.         if(!rn2(nroom * 5 / 2))
  782.             (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
  783.                      somex(croom), somey(croom), TRUE);
  784.  
  785.         /* maybe make some graffiti */
  786.         if(!rn2(27 + 3 * abs(depth(&u.uz)))) {
  787.             const char *mesg = random_engraving();
  788.             if (mesg) {
  789.             do {
  790.                 x = somex(croom);  y = somey(croom);
  791.             } while(levl[x][y].typ != ROOM && !rn2(40));
  792.             if (!(IS_POOL(levl[x][y].typ) ||
  793.                   IS_FURNITURE(levl[x][y].typ)))
  794.                 make_engr_at(x, y, mesg, 0L, MARK);
  795.             }
  796.         }
  797.  
  798. #ifdef REINCARNATION
  799.     skip_nonrogue:
  800. #endif
  801.         if(!rn2(3)) {
  802.             (void) mkobj_at(0, somex(croom), somey(croom), TRUE);
  803.             tryct = 0;
  804.             while(!rn2(5)) {
  805.             if(++tryct > 100) {
  806.                 impossible("tryct overflow4");
  807.                 break;
  808.             }
  809.             (void) mkobj_at(0, somex(croom), somey(croom), TRUE);
  810.             }
  811.         }
  812.     }
  813. }
  814.  
  815. void
  816. mklev()
  817. {
  818.     struct mkroom *croom;
  819.  
  820.     if(getbones()) return;
  821.     in_mklev = TRUE;
  822.     makelevel();
  823.     bound_digging();
  824.     in_mklev = FALSE;
  825.     /* has_morgue gets cleared once morgue entered; graveyard stays set */
  826.     level.flags.graveyard = level.flags.has_morgue;
  827.     if(!level.flags.is_maze_lev) {
  828.         for (croom = &rooms[0]; croom != &rooms[nroom]; croom++)
  829. #ifdef SPECIALIZATION
  830.         topologize(croom, FALSE);
  831. #else
  832.         topologize(croom);
  833. #endif
  834.     }
  835. }
  836.  
  837. void
  838. #ifdef SPECIALIZATION
  839. topologize(croom, do_ordinary)
  840. register struct mkroom *croom;
  841. boolean do_ordinary;
  842. #else
  843. topologize(croom)
  844. register struct mkroom *croom;
  845. #endif
  846. {
  847.     register int x, y, roomno = (croom - rooms) + ROOMOFFSET;
  848.     register int lowx = croom->lx, lowy = croom->ly;
  849.     register int hix = croom->hx, hiy = croom->hy;
  850. #ifdef SPECIALIZATION
  851.     register schar rtype = croom->rtype;
  852. #endif
  853.     register int subindex, nsubrooms = croom->nsubrooms;
  854.  
  855.     /* skip the room if already done; i.e. a shop handled out of order */
  856.     /* also skip if this is non-rectangular (it _must_ be done already) */
  857.     if (levl[lowx][lowy].roomno == roomno || croom->irregular)
  858.         return;
  859. #ifdef SPECIALIZATION
  860. # ifdef REINCARNATION
  861.     if (Is_rogue_level(&u.uz))
  862.         do_ordinary = TRUE;        /* vision routine helper */
  863. # endif
  864.     if ((rtype != OROOM) || do_ordinary)
  865. #endif
  866.     {
  867.         /* do innards first */
  868.         for(x = lowx; x <= hix; x++)
  869.         for(y = lowy; y <= hiy; y++)
  870. #ifdef SPECIALIZATION
  871.             if (rtype == OROOM)
  872.             levl[x][y].roomno = NO_ROOM;
  873.             else
  874. #endif
  875.             levl[x][y].roomno = roomno;
  876.         /* top and bottom edges */
  877.         for(x = lowx-1; x <= hix+1; x++)
  878.         for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
  879.             levl[x][y].edge = 1;
  880.             if (levl[x][y].roomno)
  881.             levl[x][y].roomno = SHARED;
  882.             else
  883.             levl[x][y].roomno = roomno;
  884.         }
  885.         /* sides */
  886.         for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
  887.         for(y = lowy; y <= hiy; y++) {
  888.             levl[x][y].edge = 1;
  889.             if (levl[x][y].roomno)
  890.             levl[x][y].roomno = SHARED;
  891.             else
  892.             levl[x][y].roomno = roomno;
  893.         }
  894.     }
  895.     /* subrooms */
  896.     for (subindex = 0; subindex < nsubrooms; subindex++)
  897. #ifdef SPECIALIZATION
  898.         topologize(croom->sbrooms[subindex], (rtype != OROOM));
  899. #else
  900.         topologize(croom->sbrooms[subindex]);
  901. #endif
  902. }
  903.  
  904. /* Find an unused room for a branch location. */
  905. static struct mkroom *
  906. find_branch_room(mp)
  907.     coord *mp;
  908. {
  909.     struct mkroom *croom = 0;
  910.  
  911.     if (nroom == 0) {
  912.     mazexy(mp);        /* already verifies location */
  913.     } else {
  914.     /* not perfect - there may be only one stairway */
  915.     if(nroom > 2) {
  916.         int tryct = 0;
  917.  
  918.         do
  919.         croom = &rooms[rn2(nroom)];
  920.         while((croom == dnstairs_room || croom == upstairs_room ||
  921.           croom->rtype != OROOM) && (++tryct < 100));
  922.     } else
  923.         croom = &rooms[rn2(nroom)];
  924.  
  925.     do {
  926.         if (!somexy(croom, mp))
  927.         impossible("Can't place branch!");
  928.     } while(occupied(mp->x, mp->y) ||
  929.         (levl[mp->x][mp->y].typ != CORR && levl[mp->x][mp->y].typ != ROOM));
  930.     }
  931.     return croom;
  932. }
  933.  
  934. /* Find the room for (x,y).  Return NULL of not in a room. */
  935. static struct mkroom *
  936. pos_to_room(x, y)
  937.     xchar x, y;
  938. {
  939.     int i;
  940.     struct mkroom *curr;
  941.  
  942.     for (curr = rooms, i = 0; i < nroom; curr++, i++)
  943.     if (inside_room(curr, x, y)) return curr;;
  944.     return (struct mkroom *) 0;
  945. }
  946.  
  947.  
  948. /* If given a branch, randomly place a special stair or portal. */
  949. void
  950. place_branch(br, x, y)
  951. branch *br;    /* branch to place */
  952. xchar x, y;    /* location */
  953. {
  954.     coord          m;
  955.     d_level          *dest;
  956.     boolean          make_stairs;
  957.     struct mkroom *br_room;
  958.  
  959.     /*
  960.      * Return immediately if there is no branch to make or we have
  961.      * already made one.  This routine can be called twice when
  962.      * a special level is loaded that specifies an SSTAIR location
  963.      * as a favored spot for a branch.
  964.      */
  965.     if (!br || made_branch) return;
  966.  
  967.     if (!x) {    /* find random coordinates for branch */
  968.         br_room = find_branch_room(&m);
  969.         x = m.x;
  970.         y = m.y;
  971.     } else {
  972.         br_room = pos_to_room(x, y);
  973.     }
  974.  
  975.     if (on_level(&br->end1, &u.uz)) {
  976.         /* we're on end1 */
  977.         make_stairs = br->type != BR_NO_END1;
  978.         dest = &br->end2;
  979.     } else {
  980.         /* we're on end2 */
  981.         make_stairs = br->type != BR_NO_END2;
  982.         dest = &br->end1;
  983.     }
  984.  
  985.     if (br->type == BR_PORTAL) {
  986.         mkportal(x, y, dest->dnum, dest->dlevel);
  987.     } else if (make_stairs) {
  988.         sstairs.sx = x;
  989.         sstairs.sy = y;
  990.         sstairs.up = (char) on_level(&br->end1, &u.uz) ?
  991.                         br->end1_up : !br->end1_up;
  992.         assign_level(&sstairs.tolev, dest);
  993.         sstairs_room = br_room;
  994.  
  995.         levl[x][y].ladder = sstairs.up ? LA_UP : LA_DOWN;
  996.         levl[x][y].typ = STAIRS;
  997.     }
  998.     /*
  999.      * Set made_branch to TRUE even if we didn't make a stairwell (i.e.
  1000.      * make_stairs is false) since there is currently only one branch
  1001.      * per level, if we failed once, we're going to fail again on the
  1002.      * next call.
  1003.      */
  1004.     made_branch = TRUE;
  1005. }
  1006.  
  1007. static boolean
  1008. bydoor(x, y)
  1009. register xchar x, y;
  1010. {
  1011.     register int typ;
  1012.  
  1013.     if (isok(x+1, y)) {
  1014.         typ = levl[x+1][y].typ;
  1015.         if (IS_DOOR(typ) || typ == SDOOR) return TRUE;
  1016.     }
  1017.     if (isok(x-1, y)) {
  1018.         typ = levl[x-1][y].typ;
  1019.         if (IS_DOOR(typ) || typ == SDOOR) return TRUE;
  1020.     }
  1021.     if (isok(x, y+1)) {
  1022.         typ = levl[x][y+1].typ;
  1023.         if (IS_DOOR(typ) || typ == SDOOR) return TRUE;
  1024.     }
  1025.     if (isok(x, y-1)) {
  1026.         typ = levl[x][y-1].typ;
  1027.         if (IS_DOOR(typ) || typ == SDOOR) return TRUE;
  1028.     }
  1029.     return FALSE;
  1030. }
  1031.  
  1032. /* see whether it is allowable to create a door at [x,y] */
  1033. int
  1034. okdoor(x,y)
  1035. register xchar x, y;
  1036. {
  1037.     register boolean near_door = bydoor(x, y);
  1038.  
  1039.     return((levl[x][y].typ == HWALL || levl[x][y].typ == VWALL) &&
  1040.             doorindex < DOORMAX && !near_door);
  1041. }
  1042.  
  1043. void
  1044. dodoor(x,y,aroom)
  1045. register int x, y;
  1046. register struct mkroom *aroom;
  1047. {
  1048.     if(doorindex >= DOORMAX) {
  1049.         impossible("DOORMAX exceeded?");
  1050.         return;
  1051.     }
  1052.  
  1053.     dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR);
  1054. }
  1055.  
  1056. boolean
  1057. occupied(x, y)
  1058. register xchar x, y;
  1059. {
  1060.     return((boolean)(t_at(x, y) || levl[x][y].typ == STAIRS
  1061.         || IS_FOUNTAIN(levl[x][y].typ)
  1062.         || IS_THRONE(levl[x][y].typ)
  1063. #ifdef SINKS
  1064.         || IS_SINK(levl[x][y].typ)
  1065. #endif
  1066.         || levl[x][y].typ == ALTAR
  1067.         || is_lava(x,y)
  1068.         || is_pool(x,y)
  1069.         || invocation_pos(x,y)
  1070.         ));
  1071. }
  1072.  
  1073. /* make a trap somewhere (in croom if mazeflag = 0 && !tm) */
  1074. /* if tm != NULL, make trap at that location */
  1075. void
  1076. mktrap(num, mazeflag, croom, tm)
  1077. register int num, mazeflag;
  1078. register struct mkroom *croom;
  1079. coord *tm;
  1080. {
  1081.     register int kind;
  1082.     coord m;
  1083.  
  1084.     /* no traps in pools */
  1085.     if (tm && is_pool(tm->x,tm->y)) return;
  1086.  
  1087.     if (num > 0 && num < TRAPNUM) {
  1088.         kind = num;
  1089. #ifdef REINCARNATION
  1090.     } else if (Is_rogue_level(&u.uz)) {
  1091.         switch (rn2(7)) {
  1092.         default: kind = BEAR_TRAP; break; /* 0 */
  1093.         case 1: kind = ARROW_TRAP; break;
  1094.         case 2: kind = DART_TRAP; break;
  1095.         case 3: kind = TRAPDOOR; break;
  1096.         case 4: kind = PIT; break;
  1097.         case 5: kind = SLP_GAS_TRAP; break;
  1098.         case 6: kind = RUST_TRAP; break;
  1099.         }
  1100. #endif
  1101.     } else if (Inhell && !rn2(5)) {
  1102.         /* bias the frequency of fire traps in Gehennom */
  1103.         kind = FIRE_TRAP;
  1104.     } else {
  1105.         unsigned lvl = level_difficulty();
  1106.  
  1107.         do {
  1108.         kind = rnd(TRAPNUM-1);
  1109.         /* reject "too hard" traps */
  1110.         switch (kind) {
  1111.             case SLP_GAS_TRAP:
  1112.             if (lvl < 2) kind = NO_TRAP; break;
  1113.             case LEVEL_TELEP:
  1114.             if (lvl < 5 || level.flags.noteleport)
  1115.                 kind = NO_TRAP; break;
  1116.             case SPIKED_PIT:
  1117.             if (lvl < 5) kind = NO_TRAP; break;
  1118.             case LANDMINE:
  1119.             if (lvl < 6) kind = NO_TRAP; break;
  1120.             case WEB:
  1121.             if (lvl < 7) kind = NO_TRAP; break;
  1122.             case STATUE_TRAP:
  1123. #ifdef POLYSELF
  1124.             case POLY_TRAP:
  1125. #endif
  1126.             if (lvl < 8) kind = NO_TRAP; break;
  1127.             case FIRE_TRAP:
  1128.             if (!Inhell) kind = NO_TRAP; break;
  1129.             case TELEP_TRAP:
  1130.             if (level.flags.noteleport) kind = NO_TRAP; break;
  1131.         }
  1132.         } while (kind == NO_TRAP || kind == MAGIC_PORTAL);
  1133.     }
  1134.  
  1135.     if (kind == TRAPDOOR && !Can_fall_thru(&u.uz)) kind = ROCKTRAP;
  1136.  
  1137.     if (tm)
  1138.         m = *tm;
  1139.     else {
  1140.         register int tryct = 0;
  1141.  
  1142.         do {
  1143.         if (++tryct > 200)
  1144.             return;
  1145.         if (mazeflag)
  1146.             mazexy(&m);
  1147.         else if (!somexy(croom,&m))
  1148.             return;
  1149.         } while (occupied(m.x, m.y) || is_pool(m.x,m.y) ||
  1150.                      (sobj_at(BOULDER, m.x, m.y) &&
  1151.                       (kind == PIT || kind == SPIKED_PIT ||
  1152.                        kind == TRAPDOOR)));
  1153.     }
  1154.  
  1155.     (void) maketrap(m.x, m.y, kind);
  1156.     if (kind == WEB) (void) makemon(&mons[PM_GIANT_SPIDER], m.x, m.y);
  1157. }
  1158.  
  1159. void
  1160. mkstairs(x, y, up, croom)
  1161. xchar x, y;
  1162. char  up;
  1163. struct mkroom *croom;
  1164. {
  1165.     if (! (x || y)) {
  1166.         impossible("mkstairs:  bogus stair attempt at (%d,%d)", x, y);
  1167.         return;
  1168.     }
  1169.  
  1170.     /*
  1171.      * We can't make a regular stair off an end of the dungeon.  This
  1172.      * attempt can happen when a special level is placed at an end and
  1173.      * has an up or down stair specified in its description file.
  1174.      */
  1175.     if ((dunlev(&u.uz) == 1 && up) ||
  1176.             (dunlev(&u.uz) == dunlevs_in_dungeon(&u.uz) && !up))
  1177.         return;
  1178.  
  1179.     if(up) {
  1180.         xupstair = x;
  1181.         yupstair = y;
  1182.         upstairs_room = croom;
  1183.     } else {
  1184.         xdnstair = x;
  1185.         ydnstair = y;
  1186.         dnstairs_room = croom;
  1187.     }
  1188.  
  1189.     levl[x][y].typ = STAIRS;
  1190.     levl[x][y].ladder = up ? LA_UP : LA_DOWN;
  1191. }
  1192.  
  1193. static
  1194. void
  1195. mkfount(mazeflag,croom)
  1196. register int mazeflag;
  1197. register struct mkroom *croom;
  1198. {
  1199.     coord m;
  1200.     register int tryct = 0;
  1201.  
  1202.     do {
  1203.         if(++tryct > 200) return;
  1204.         if(mazeflag)
  1205.         mazexy(&m);
  1206.         else
  1207.         if (!somexy(croom, &m))
  1208.             return;
  1209.     } while(occupied(m.x, m.y) || bydoor(m.x, m.y));
  1210.  
  1211.     /* Put a fountain at m.x, m.y */
  1212.     levl[m.x][m.y].typ = FOUNTAIN;
  1213.     /* Is it a "blessed" fountain? (affects drinking from fountain) */
  1214.     if(!rn2(7)) levl[m.x][m.y].blessedftn = 1;
  1215.  
  1216.     level.flags.nfountains++;
  1217. }
  1218.  
  1219. #ifdef SINKS
  1220. static void
  1221. mksink(croom)
  1222. register struct mkroom *croom;
  1223. {
  1224.     coord m;
  1225.     register int tryct = 0;
  1226.  
  1227.     do {
  1228.         if(++tryct > 200) return;
  1229.         if (!somexy(croom, &m))
  1230.         return;
  1231.     } while(occupied(m.x, m.y) || bydoor(m.x, m.y));
  1232.  
  1233.     /* Put a sink at m.x, m.y */
  1234.     levl[m.x][m.y].typ = SINK;
  1235.  
  1236.     level.flags.nsinks++;
  1237. }
  1238. #endif /* SINKS /**/
  1239.  
  1240.  
  1241. static void
  1242. mkaltar(croom)
  1243. register struct mkroom *croom;
  1244. {
  1245.     coord m;
  1246.     register int tryct = 0;
  1247.     aligntyp al;
  1248.  
  1249.     if(croom->rtype != OROOM) return;
  1250.  
  1251.     do {
  1252.         if(++tryct > 200) return;
  1253.         if (!somexy(croom, &m))
  1254.         return;
  1255.     } while(occupied(m.x, m.y) || bydoor(m.x, m.y));
  1256.  
  1257.     /* Put an altar at m.x, m.y */
  1258.     levl[m.x][m.y].typ = ALTAR;
  1259.  
  1260.     /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
  1261.     al = rn2((int)A_LAWFUL+2) - 1;
  1262.     levl[m.x][m.y].altarmask = Align2amask( al );
  1263. }
  1264.  
  1265. /*
  1266.  * Major level transmutation: add a set of stairs (to the Sanctum) after
  1267.  * an earthquake that leaves behind a a new topology, centered at inv_pos.
  1268.  * Assumes there are no rooms within the invocation area and that inv_pos
  1269.  * is not too close to the edge of the map.  Also assume the hero can see.
  1270.  */
  1271. void
  1272. mkinvokearea()
  1273. {
  1274.     int dist;
  1275.     xchar xmin = inv_pos.x, xmax = inv_pos.x;
  1276.     xchar ymin = inv_pos.y, ymax = inv_pos.y;
  1277.     register xchar i;
  1278.  
  1279.     pline("The floor shakes violently under you!");
  1280.     pline("The walls around you begin to bend and crumble!");
  1281.     display_nhwindow(WIN_MESSAGE, TRUE);
  1282.  
  1283.     for(dist = 1; dist < 7; dist++) {
  1284.     xmin--; xmax++;
  1285.  
  1286.     /* top and bottom */
  1287.     if(dist != 3) { /* the area is wider that it is high */
  1288.         ymin--; ymax++;
  1289.         for(i = xmin+1; i < xmax; i++) {
  1290.         mkinvpos(i, ymin, dist);
  1291.         mkinvpos(i, ymax, dist);
  1292.         }
  1293.     }
  1294.  
  1295.     /* left and right */
  1296.     for(i = ymin; i <= ymax; i++) {
  1297.         mkinvpos(xmin, i, dist);
  1298.         mkinvpos(xmax, i, dist);
  1299.     }
  1300.  
  1301.     flush_screen(1);    /* make sure the new glyphs shows up */
  1302.     delay_output();
  1303.     }
  1304.  
  1305.     You("are standing at the top of a stairwell leading down!");
  1306.     mkstairs(u.ux, u.uy, 0, (struct mkroom *)0); /* down */
  1307.     newsym(u.ux, u.uy);
  1308.     vision_full_recalc = 1;    /* everything changed */
  1309. }
  1310.  
  1311. /* Change level topology.  Messes with vision tables and ignores things like
  1312.  * boulders in the name of a nice effect.  Vision will get fixed up again
  1313.  * immediately after the effect is complete.
  1314.  */
  1315. static void
  1316. mkinvpos(x,y,dist)
  1317. xchar x,y;
  1318. int dist;
  1319. {
  1320.     struct trap *ttmp;
  1321.     register struct rm *lev = &levl[x][y];
  1322.  
  1323.     unblock_point(x,y);    /* make sure vision knows this location is open */
  1324.  
  1325.     /* fake out saved state */
  1326.     lev->seen = FALSE;
  1327.     lev->doormask = 0;
  1328.     if(dist < 6) lev->lit = TRUE;
  1329.     lev->waslit = TRUE;
  1330.     lev->horizontal = FALSE;
  1331.     viz_array[y][x] = (dist < 6 ) ?
  1332.     (IN_SIGHT|COULD_SEE) : /* short-circuit vision recalc */
  1333.     COULD_SEE;
  1334.  
  1335.     switch(dist) {
  1336.     case 1: /* fire traps */
  1337.     lev->typ = ROOM;
  1338.     if (is_pool(x,y)) break;
  1339.     ttmp = maketrap(x, y, FIRE_TRAP);
  1340.     if (ttmp) ttmp->tseen = TRUE;
  1341.     break;
  1342.     case 2: /* lit room locations */
  1343.     case 3:
  1344.     case 6:
  1345.     if ((ttmp = t_at(x,y)) != 0) deltrap(ttmp);
  1346.     lev->typ = ROOM;
  1347.     break;
  1348.     case 4: /* pools (aka a wide moat) */
  1349.     case 5:
  1350.     if ((ttmp = t_at(x,y)) != 0) deltrap(ttmp);
  1351.     lev->typ = MOAT;
  1352.     break;
  1353.     default:
  1354.     impossible("mkinvpos called with dist %d", dist);
  1355.     break;
  1356.     }
  1357.  
  1358.     /* display new value of position; could have a monster/object on it */
  1359.     newsym(x,y);
  1360. }
  1361.  
  1362. #ifdef MULDGN
  1363. /*
  1364.  * The portal to Ludios is special.  The entrance can only occur within a
  1365.  * vault in the main dungeon at a depth greater than 10.  The Ludios branch
  1366.  * structure reflects this by having a bogus "source" dungeon:  the value
  1367.  * of n_dgns (thus, Is_branchlev() will never find it).
  1368.  *
  1369.  * Ludios will remain isolated until the branch is corrected by this function.
  1370.  */
  1371. static void
  1372. mk_knox_portal(x, y)
  1373. xchar x, y;
  1374. {
  1375.     extern int n_dgns;        /* from dungeon.c */
  1376.     d_level *source;
  1377.     branch *br;
  1378.     schar u_depth;
  1379.  
  1380.     br = dungeon_branch("Fort Ludios");
  1381.     if (on_level(&knox_level, &br->end1)) {
  1382.         source = &br->end2;
  1383.     } else {
  1384.         /* disallow Knox branch on a level with one branch already */
  1385.         if(Is_branchlev(&u.uz))
  1386.         return;
  1387.         source = &br->end1;
  1388.     }
  1389.  
  1390.     /* Already set or 2/3 chance of deferring until a later level. */
  1391.     if (source->dnum < n_dgns || (rn2(3)
  1392. #ifdef WIZARD
  1393.                       && !wizard
  1394. #endif
  1395.                       )) return;
  1396.  
  1397.     if (! (u.uz.dnum == oracle_level.dnum        /* in main dungeon */
  1398.         && !at_dgn_entrance("The Quest")    /* but not Quest's entry */
  1399.         && (u_depth = depth(&u.uz)) > 10    /* beneath 10 */
  1400.         && u_depth < depth(&medusa_level))) /* and above Medusa */
  1401.         return;
  1402.  
  1403.     /* Adjust source to be current level and re-insert branch. */
  1404.     *source = u.uz;
  1405.     insert_branch(br, TRUE);
  1406.  
  1407. # ifdef DEBUG
  1408.     pline("Made knox portal.");
  1409. # endif
  1410.     place_branch(br, x, y);
  1411. }
  1412. #endif
  1413.  
  1414. /*mklev.c*/
  1415.